<template>
  <div class="content">

    <!--搜索-->
    <div ref="searchDiv">
      <a-form
          ref="defSearch"
          :model="defSearch.param"
          :rules="defSearch.rules"
          :labelCol="defSearch.labelCol"
          class="search_form shadow3">

        <!--搜索条件-->
        <div class="fx_row fx_wrap fx_start" style="width: calc(100%)">
          <a-form-item label="角色名称" name="name" style="width: 220px">
            <a-input allow-clear v-model:value="defSearch.param.name" placeholder="请输入角色名称"></a-input>
          </a-form-item>

          <a-form-item label="权限字符" name="roleKey" style="width: 220px">
            <a-input allow-clear v-model:value="defSearch.param.roleKey" placeholder="请输入权限字符"></a-input>
          </a-form-item>

          <a-form-item label="状态" name="status" style="width: 170px">
            <a-select v-model:value="defSearch.param.status" placeholder="请选择" :allowClear="true">
              <a-select-option v-for="(item,index) in option.status" :value=item.value>
                {{
                  item.label
                }}
              </a-select-option>
            </a-select>
          </a-form-item>

        </div>

        <!--按钮-->
        <a-form-item class="search_button_2">
          <a-button type="primary" @click.stop="search" class="font12">
            <template #icon>
              <SearchOutlined/>
            </template>
            查询
          </a-button>
          <a-button style="margin-left: 10px" @click.stop="()=>{ resetForm('defSearch'); }" class="font12">
            <template #icon>
              <UndoOutlined/>
            </template>
            重置
          </a-button>
        </a-form-item>

      </a-form>
    </div>

    <!--表格选项-->
    <div class="table_tools">
      <a-button class="font11" type="primary" size="small" ghost @click.stop="openAdd(null)">
        <template #icon>
          <plus-outlined/>
        </template>
        新建
      </a-button>

      <div class="fx_110"></div>

      <!--      <a-tooltip placement="top">-->
      <!--        <template #title>-->
      <!--          <span>批量删除</span>-->
      <!--        </template>-->
      <!--        <delete-outlined :style="{fontSize: '16px'}" @click.stop="delRoleBatch"/>-->
      <!--      </a-tooltip>-->

      <!--      <a-divider type="vertical"/>-->

      <a-tooltip placement="top">
        <template #title>
          <span>表格大小</span>
        </template>
        <a-dropdown :trigger="['click']">
          <setting-outlined :style="{fontSize: '16px'}"/>
          <template #overlay>
            <a-menu v-model:selectedKeys="defTable.size" @click="(item)=>{defTable.size=item.key+''}">
              <a-menu-item v-for="(item,index) in option.tableSize" :key="item.value">
                <div style="padding: 0 5px">
                  {{ item.label }}
                </div>
              </a-menu-item>
            </a-menu>
          </template>
        </a-dropdown>

      </a-tooltip>

    </div>

    <!--表格-->
    <div ref="tableDiv" :style="{background:'#FFFFFF',minHeight:option.tableMinHeight}">
      <a-table
          sticky
          ref="defTable"
          rowKey="id"
          style="height: 100%"
          :pagination="false"
          :size="defTable.size"
          :columns="defTable.column"
          :expandRowByClick="true"
          :data-source="defTable.data"
          :rowSelection="defTable.rowSelection()"
          @resizeColumn="(w, col) => {col.width = w;}">

        <!--表格内容-->
        <template #bodyCell="{ text, record, index, column  }">
          <!--目录-->
          <template v-if="column.dataIndex === 'name'">
            <a-tag color="blue">
              {{ text }}
            </a-tag>
          </template>

          <template v-if="column.dataIndex === 'role_key'">
            <a-tag>
              {{ text }}
            </a-tag>
          </template>

          <template v-if="column.dataIndex === 'status'">
            <a-tag v-if="text==0" color="green" class="round">启用</a-tag>
            <a-tag v-if="text==1" color="orange" class="round">停用</a-tag>
          </template>

          <!--操作-->
          <template v-if="column.dataIndex === 'action'">

            <!--编辑-->
            <a @click.stop="openEdit(record)" class="table_action_a">编辑</a>

            <!--删除-->
            <a-divider v-if="record.role_key!='root'" type="vertical"/>
            <a-popconfirm v-if="record.role_key!='root'" placement="bottomRight" ok-text="确定" cancel-text="取消"
                          @click.stop
                          @confirm="deleteRole(record)">
              <template #title>
                <p>是否执行删除操作?</p>
              </template>
              <a class="table_action_a">删除</a>
            </a-popconfirm>

            <!--更多、复制新增-->
            <a-divider type="vertical"/>
            <a-dropdown>
              <a class="table_action_a" @click.stop @click.prevent>更多
                <DownOutlined/>
              </a>
              <template #overlay>
                <a-menu>
                  <a-menu-item class="hover_blue table_action_a" @click.stop="openCopyAdd(record)">
                    复制新增
                  </a-menu-item>
                  <a-menu-item class="hover_blue table_action_a" @click.stop="openEditApi(record)">
                    API权限
                  </a-menu-item>
                </a-menu>
              </template>
            </a-dropdown>

          </template>

        </template>

        <!--      &lt;!&ndash;额外展开行&ndash;&gt;-->
        <!--      <template #expandedRowRender="{ record }">-->
        <!--        <p style="margin: 0">-->
        <!--          {{ record.description }}-->
        <!--        </p>-->
        <!--      </template>-->

      </a-table>
    </div>

    <!--分页-->
    <Pagination class="table_page"
                :current="defPage.current"
                :total="defPage.total"
                :page-size="defPage.size"
                @change="defPage.change"/>

    <!--新增Dialog-->
    <a-modal
        title="新增角色"
        style="width:80%;min-width: 800px"
        :maskClosable="false"
        :destroyOnClose="true"
        v-model:visible="option.openAdd">

      <!--表单-->
      <a-form
          ref="defForm"
          label-align="right"
          :model="defForm.data"
          :rules="defForm.rules"


          :scrollToFirstError="true">

        <a-form-item label="角色名称" name="name">
          <a-input v-model:value="defForm.data.name" placeholder="请输入角色名称" :allowClear="true"/>
        </a-form-item>

        <a-form-item label="权限字符" name="role_key">
          <a-input v-model:value="defForm.data.role_key" placeholder="请输入权限字符" :allowClear="true"/>
        </a-form-item>

        <a-form-item label="状态" name="status">
          <a-radio-group v-model:value="defForm.data.status">
            <a-radio value="0">启用</a-radio>
            <a-radio value="1">停用</a-radio>
          </a-radio-group>
        </a-form-item>

        <a-form-item label="排序" name="sort">
          <a-input-number v-model:value="defForm.data.sort" :min="1" :max="99999"/>
        </a-form-item>

        <a-form-item label="描述信息" name="desc">
          <a-textarea show-count :maxlength="200" v-model:value="defForm.data.desc" placeholder="请输入描述信息"
                      :rows="3"/>
        </a-form-item>

        <a-divider style="margin: 0 0 20px 0;padding: 0"></a-divider>
        <h3>菜单权限</h3>
        <div style="margin-left: 30px">
          <!--表格-->
          <a-table
              sticky
              ref="menuTable"
              rowKey="id"
              :pagination="false"
              :size="menuTable.size"
              :columns="menuTable.column"
              :data-source="menuTable.data"
              :rowSelection="menuTable.rowSelection()"
              @resizeColumn="(w, col) => {col.width = w;}">

            <!--表格内容-->
            <template #bodyCell="{ text, record, index, column  }">
              <!--目录-->
              <template v-if="column.dataIndex === 'name'">
                <span v-if="record.type==0||record.type==1"> {{ text }}</span>
                <a-tag v-else> {{ text }}</a-tag>
              </template>

              <template v-if="column.dataIndex === 'apis'">

                <tempalte v-if="text">
                  <a-tooltip placement="top">
                    <template #title>
                      <a v-for=" (item,index) in JSON.parse(text)">
                        {{ item }} &nbsp;
                      </a>
                    </template>
                    <a-tag v-for=" (item,index) in JSON.parse(text)">
                      {{ item }}
                    </a-tag>
                  </a-tooltip>
                </tempalte>

                <tempalte v-else>
                  #
                </tempalte>

              </template>

              <template v-if="column.dataIndex === 'path'">
                <span v-if="text">{{ text }}</span>
                <span v-else>#</span>
              </template>

              <template v-if="column.dataIndex === 'type'">
                <a-tag v-if="text==0" color="blue" class="round">目录</a-tag>
                <a-tag v-else-if="text==1" color="green" class="round">菜单</a-tag>
                <a-tag v-else color="yellow" class="round">功能</a-tag>
              </template>
            </template>

          </a-table>

        </div>
      </a-form>

      <!--底部按钮-->
      <template #footer>
        <a-button @click.stop="()=>{option.openAdd = false}">取消</a-button>
        <!--        <a-button @click.stop="()=>{resetForm('defForm')}">重置</a-button>-->
        <a-button type="primary" @click.stop="addRole">保存</a-button>
      </template>

    </a-modal>

    <!--编辑Dialog-->
    <a-modal
        title="编辑角色信息"
        style="width:80%;min-width: 800px"
        :maskClosable="false"
        :destroyOnClose="true"
        v-model:visible="option.openEdit">

      <!--表单-->
      <a-form
          ref="defForm"
          label-align="right"
          :model="defForm.data"
          :rules="defForm.rules"
          :labelCol="{style: {width: '80px'}}"
          :scrollToFirstError="true">
        <a-form-item label="ID" name="id">
          <a-input disabled type="number" v-model:value="defForm.data.id" placeholder="请输入唯一ID" :allowClear="true"/>
        </a-form-item>

        <a-form-item label="角色名称" name="name">
          <a-input v-model:value="defForm.data.name" placeholder="请输入角色名称" :allowClear="true"/>
        </a-form-item>

        <a-form-item label="权限字符" name="role_key">
          <a-input disabled v-model:value="defForm.data.role_key" placeholder="请输入权限字符" :allowClear="true"/>
        </a-form-item>

        <a-form-item label="状态" name="status">
          <a-radio-group v-model:value="defForm.data.status">
            <a-radio value="0">启用</a-radio>
            <a-radio value="1">停用</a-radio>
          </a-radio-group>
        </a-form-item>

        <a-form-item label="排序" name="sort">
          <a-input-number v-model:value="defForm.data.sort" :min="1" :max="99999"/>
        </a-form-item>

        <a-form-item label="描述信息" name="desc">
          <a-textarea show-count :maxlength="200" v-model:value="defForm.data.desc" placeholder="请输入描述信息"
                      :rows="3"/>
        </a-form-item>

        <a-divider style="margin: 0 0 20px 0;padding: 0"></a-divider>
        <h3>菜单权限</h3>
        <!--表格-->
        <a-table
            sticky
            ref="menuTable"
            rowKey="id"
            :pagination="false"
            :size="menuTable.size"
            :columns="menuTable.column"
            :data-source="menuTable.data"
            :rowSelection="menuTable.rowSelection()"
            style="padding-left: 20px"
            @resizeColumn="(w, col) => {col.width = w;}">

          <!--表格内容-->
          <template #bodyCell="{ text, record, index, column  }">
            <!--目录-->
            <template v-if="column.dataIndex === 'name'">
              <span v-if="record.type==0||record.type==1"> {{ text }}</span>
              <a-tag v-else> {{ text }}</a-tag>
            </template>

            <template v-if="column.dataIndex === 'apis'">

              <tempalte v-if="text">
                <a-tooltip placement="top">
                  <template #title>
                    <a v-for=" (item,index) in JSON.parse(text)">
                      {{ item }} &nbsp;
                    </a>
                  </template>
                  <a-tag v-for=" (item,index) in JSON.parse(text)">
                    {{ item }}
                  </a-tag>
                </a-tooltip>
              </tempalte>

              <tempalte v-else>
                #
              </tempalte>

            </template>

            <template v-if="column.dataIndex === 'path'">
              <span v-if="text">{{ text }}</span>
              <span v-else>#</span>
            </template>

            <template v-if="column.dataIndex === 'type'">
              <a-tag v-if="text==0" color="blue" class="round">目录</a-tag>
              <a-tag v-else-if="text==1" color="green" class="round">菜单</a-tag>
              <a-tag v-else color="yellow" class="round">功能</a-tag>
            </template>
          </template>

        </a-table>
      </a-form>

      <!--底部按钮-->
      <template #footer>
        <a-button @click.stop="()=>{this.option.openEdit = false}">取消</a-button>
        <!--        <a-button @click.stop="()=>{resetForm('defForm')}">重置</a-button>-->
        <a-button type="primary" @click.stop="editRole">保存</a-button>
      </template>

    </a-modal>

    <select-api v-if="option.openSelectApi" @close="()=>{this.option.openSelectApi=false}" @ok="()=>{}"></select-api>
  </div>
</template>

<script lang="ts">
import {DeleteOutlined, PlusOutlined, SearchOutlined, UndoOutlined} from "@ant-design/icons-vue";
import {requiredBlur, requiredChange} from "@/common/util/validate";
import {TreeSelect} from "ant-design-vue";
import {refreshMenu} from "@/common/api/common";
import {useUserStore} from "@/common/store/modules/user";
import {ModalKit} from "@/common/util/ModalKit";
import {useLayoutStore} from "@/common/store/modules/layout";
import Pagination from "@/common/component/Pagination.vue";
import SelectApi from "@/module/system/component/SelectApi.vue";
import {copyObj, toJsonObject, toSetArray} from "@/common/util/kit";
import {parseTree} from "@/common/util/tree";

export default {
  components: {SelectApi, Pagination, DeleteOutlined, SearchOutlined, UndoOutlined, PlusOutlined},
  mounted() {
    this.queryPage()
    //全局监听-刷新当前页面
    this.$event.$on('refresh', (data) => {
      if (this.$route.path == data['path']) {
        this.resetForm('defSearch');
        this.queryPage()
      }
    })
    //更新表格大小
    this.$nextTick(() => {
      this.calcDefaultTableHeight()
    })
    //监控窗口大小变更
    window.onresize = () => {
      this.calcDefaultTableHeight()
    }
  },
  data() {
    return {
      //树形关联勾选需要
      SHOW_ALL: TreeSelect.SHOW_ALL,
      //store
      userStore: useUserStore(),
      //选项
      option: {
        openAdd: false,
        openEdit: false,
        openInfo: false,
        openSelectApi: false,
        tableMinHeight: '100%',
        tableSize: [
          {label: '大号', value: 'default'},
          {label: '中号', value: 'middle'},
          {label: '小号', value: 'small'},
        ],
        status: [
          {label: '启用', value: '0'},
          {label: '停用', value: '1'},
        ],
        menuTree: [],
        apiTree: [],
      },

      //搜索表单（默认）
      defSearch: {
        param: {
          name: undefined,
          roleKey: undefined,
          roleStatus: undefined,
        },
        rules: {},
        labelCol: {style: {width: '60px'}},
      },

      //表单（默认）
      defForm: {
        //实际表单数据
        data: {},
        initData: {
          sort: '100',
          status: '0',
          desc: '',
          name: '',
          role_key: '',
        },
        rules: {
          id: [requiredBlur],
          name: [requiredBlur],
          sort: [requiredBlur],
          status: [requiredBlur],
          role_key: [requiredBlur],
        },
      },

      //表单（菜单功能）
      funForm: {
        //实际表单数据
        data: {
          sort: 1,
          menuName: undefined,
          name: undefined,
          apis: [],
        },
        rules: {
          name: [requiredBlur],
          sort: [requiredBlur],
          apis: [requiredChange],
        },
      },

      //表格数据（默认）
      defTable: {
        size: 'middle',
        data: [],
        column: [
          {title: 'ID', dataIndex: 'id', ellipsis: true, width: 100, align: 'center', resizable: true},
          {title: '角色名称', dataIndex: 'name', resizable: true},
          {title: '权限字符', dataIndex: 'role_key', resizable: true,},
          {title: '状态', dataIndex: 'status', resizable: true, align: 'center', width: 60},
          {title: '排序', dataIndex: 'sort', resizable: true, align: 'center', width: 80},
          {title: '创建时间', dataIndex: 'd_ct', resizable: true, ellipsis: true},
          {title: '修改时间', dataIndex: 'd_ut', resizable: true, ellipsis: true},
          {title: '描述信息', dataIndex: 'desc', resizable: true, ellipsis: true},
          {title: '操作', dataIndex: 'action', align: 'center', width: 180},
        ],
        selectKey: [],
        selectRow: [],
        rowSelection: () => {
          return {
            type: "checkbox",
            checkStrictly: false,
            preserveSelectedRowKeys: false,//翻页后保留选中状态
            selectedRowKeys: this.defTable.selectKey,
            onChange: (selectedRowKeys, selectedRows) => {
              this.defTable.selectKey = selectedRowKeys
              this.defTable.selectRow = selectedRows
            },
            onSelect: (record, selected, selectedRows) => {
            },
            onSelectAll: (selected, selectedRows, changeRows) => {
            },
          }
        },
      },

      //表格数据（默认）
      menuTable: {
        size: 'small',
        data: [],
        originData: [],
        column: [
          {title: '名称', dataIndex: 'name', resizable: true, align: 'center'},
          {title: '类型', dataIndex: 'type', resizable: true, align: 'center', width: 80},
          {title: '访问地址', dataIndex: 'path', resizable: true, align: 'center'},
        ],
        selectKey: [],
        selectRow: [],
        rowSelection: () => {
          return {
            type: "checkbox",
            checkStrictly: false,
            preserveSelectedRowKeys: false,//翻页后保留选中状态
            selectedRowKeys: this.menuTable.selectKey,
            onChange: (selectedRowKeys, selectedRows) => {
              this.menuTable.selectKey = selectedRowKeys
              this.menuTable.selectRow = selectedRows
            },
            onSelect: (record, selected, selectedRows) => {
            },
            onSelectAll: (selected, selectedRows, changeRows) => {
            },
          }
        },
      },

      //分页（默认）
      defPage: {
        current: 1,
        size: 10,
        total: 0,
        type: 'small',
        change: (current, pageSize) => {
          this.defPage.current = current;
          this.defPage.size = pageSize;
          this.queryPage()
        }
      },
    }
  },
  methods: {
    //查询分页
    async queryPage() {
      useLayoutStore().pageLoading = true;

      await refreshMenu();

      let param = copyObj(this.defSearch.param)
      param.size = this.defPage.size
      param.current = this.defPage.current

      this.$http.post('/system/role/list', param).then((res) => {
        //分页
        this.defPage.total = res.total * 1
        //数据
        this.defTable.data = res.data
        useLayoutStore().pageLoading = false;

      })
    },
    //搜索
    search() {
      this.$refs.defSearch.validate().then(() => {
        this.queryPage()
      }).catch(error => {
        this.$message.warning("存在错误，请检查表单填写情况。", 2)
      });

    },
    //重置表单（还原）
    resetForm(formName) {
      let form = this.$refs[formName]
      if (form) {
        form.resetFields()
      }
    },
    //打开新增Dialog
    async openAdd(record) {
      await this.queryMenuPage()
      this.defForm.data = copyObj(this.defForm.initData)
      this.menuTable.selectKey = []
      this.option.openAdd = true;
    },
    //详情
    async openInfo(record) {
      await this.queryMenuPage()
      this.defForm.data = copyObj(record);
      this.option.openInfo = true;
    },
    //打开复制并新增
    async openCopyAdd(record) {
      await this.queryMenuPage()
      this.defForm.data = copyObj(record);
      this.menuTable.selectKey = JSON.parse(this.defForm.data.check_menu_ids)
      this.updateMenuTable()
      this.option.openAdd = true;
    },
    //打开编辑接口权限
    openEditApi(record) {
      this.option.openSelectApi = true
    },
    //打开编辑菜单Dialog
    async openEdit(record) {
      await this.queryMenuPage()
      this.option.openEdit = true;
      this.defForm.data = copyObj(record);
      this.updateMenuTable()
    },
    updateMenuTable() {
      this.menuTable.selectKey = toJsonObject(this.defForm.data.check_menu_ids)
      let selectRow = []
      this.menuTable.originData.filter(data => {
        this.menuTable.selectKey.filter(id => {
          if (id == data.id) {
            selectRow.push(data);
          }
        })
      })
      this.menuTable.selectRow = selectRow
    },
    //添加
    addRole(record) {
      this.$refs.defForm.validate()
          .then(() => {
            let submitForm = copyObj(this.defForm.data)
            //回显时使用
            submitForm.check_menu_ids = this.getCheckMenuIds()
            //角色关联菜单
            submitForm.menuIds = this.getRoleMenuIds()

            this.$http.post("/system/role/add", submitForm).then((res) => {
              this.$message.success(res.message, 1)
              this.queryPage()
              this.option.openAdd = false
            })

          })
          .catch(error => {
            this.$message.warning("存在错误，请检查表单填写情况。", 2)
          });
    },
    //编辑
    editRole(record) {
      this.$refs.defForm.validate()
          .then(() => {
            let submitForm = copyObj(this.defForm.data)
            //回显时使用
            submitForm.check_menu_ids = this.getCheckMenuIds()
            //角色关联菜单
            submitForm.menuIds = this.getRoleMenuIds()
            //console.log("【submitForm】", JSON.stringify(submitForm))

            // apis TODO 编辑
            this.$http.post("/system/role/edit", submitForm).then((res) => {
              this.$message.success(res.message, 1)
              this.queryPage()
              this.option.openEdit = false
            })

          })
          .catch(error => {
            this.$message.warning("存在错误，请检查表单填写情况。", 2)
          });
    },
    //角色关联菜单
    getRoleMenuIds() {
      let menuIds = []
      this.menuTable.selectRow.filter(e => {
        menuIds.push(...JSON.parse(e.ids))
      })
      return toSetArray(menuIds)
    },
    //回显时使用
    getCheckMenuIds() {
      //回显IDS， check_menu_ids：删除pid不为0且存在子节点的数据
      let keys = toJsonObject(this.menuTable.selectKey)
      let selectRow = []
      this.menuTable.originData.filter(data => {
        keys.filter(key => {
          if (key == data.id && data.first_children_count == '0') {
            //console.log("【data】", data)
            selectRow.push(data);
          }
        })
      })
      let check_menu_ids = selectRow.map(e => e.id)
      //console.log("【keys】", keys)
      //console.log("【selectRow】", selectRow)
      //console.log("【check_menu_ids】", check_menu_ids)
      return check_menu_ids;
    },
    //删除
    deleteRole(record) {
      this.$http.post("/system/role/del", {ids: [record.id]}).then((res) => {
        this.$message.success(res.message, 1)
        this.queryPage()
      })
    },
    //批量删除
    delRoleBatch() {
      let keys = this.defTable.selectKey;
      if (keys.length === 0) {
        this.$message.warn("请至少勾选一项", 1)
        return
      }

      ModalKit.confirm(
          `已勾选${keys.length}条数据，是否执行批量删除？`,
          () => {
            this.$http.post("/system/role/del", {ids: keys}).then((res) => {
              this.$message.success(res.message, 1)
              this.queryPage()
            })
          },
          () => {
            this.$message.warning("操作已取消", 1)
          }
      )
    },
    //查询菜单
    async queryMenuPage() {
      return this.$http.post('/system/menu/list', {}).then((res) => {
        this.menuTable.data = parseTree(res.data)
        this.menuTable.originData = res.data
      })
    },
    //查询接口权限
    async queryAPI() {
      return this.$http.post('/system/api/list', {}).then((res) => {
        this.menuTable.data = parseTree(res.data)
      })
    },
    //计算表格高度，最小要求铺满窗口
    calcDefaultTableHeight() {
      //减去 （搜索表单、表格工具栏、外边距、分页(60px)）
      let searchDiv = this.$refs.searchDiv.offsetHeight
      let tableToolDiv = 50
      let margin = 32;
      let page = 60

      this.option.tableMinHeight = `calc(100% - ${searchDiv}px - ${tableToolDiv}px - ${margin}px - ${page}px)`;
      //console.log(" searchDiv ", searchDiv)
      //console.log(" tableToolDiv ", tableToolDiv)
      //console.log(" this.defTable.minHeight", this.defTable.minHeight)
    },
  }
}


</script>

<style lang="less">

</style>

<style scoped lang="less">

</style>
